home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
C/C++ Users Group Library 1996 July
/
C-C++ Users Group Library July 1996.iso
/
vol_300
/
355_02
/
slk2.exe
/
SPP
/
EXP.C
< prev
next >
Wrap
C/C++ Source or Header
|
1991-06-09
|
7KB
|
367 lines
/*
New Sherlock preprocessor -- expression routines.
Source: exp.c
Started: September 28, 1987
Version:
July 15, 1988
February 15, 1989
periods removed from error messages.
June 22, 1989
curly_ok_flag kludge added to is_delim().
PUBLIC DOMAIN SOFTWARE
Sherlock, including the SPP, SDEL and SDIF programs, was placed in
the public domain on June 15, 1991, by its author,
Edward K. Ream
166 North Prospect Ave.
Madison, WI 53705.
(608) 257-0802
Sherlock may be used for any commercial or non-commercial purpose.
DISCLAIMER OF WARRANTIES
Edward K. Ream (Ream) specifically disclaims all warranties,
expressed or implied, with respect to this computer software,
including but not limited to implied warranties of merchantability
and fitness for a particular purpose. In no event shall Ream be
liable for any loss of profit or any commercial damage, including
but not limited to special, incidental consequential or other damages.
*/
#include "spp.h"
#undef TRACETOK
#define TRACETOK(name) TICK(name)
/* Declare parsing routines defined in this file. */
static void exp_index(void);
static void exp_op(void);
static void exp_postop(void);
static bool exp_preop(void);
static void exp_term(void);
static bool is_delim(en_tokens delim);
/* =============== Externally visible routines =============== */
/*
Parse an expression, terminated by delim.
This routine is called recursively whenever '(' or '[' is seen.
*/
void
con_expr(en_tokens delim)
{
TRACEP("con_expr", printf("(%s)\n", pr_op(delim)));
expr(delim);
}
/*
Parse an expression, assumed to end with delim, but do NOT eat delim.
Null expressions are valid. Comma operators are valid.
*/
void
expr(en_tokens delim)
{
TRACEP("expr", printf("(%s)\n", pr_op(delim)));
/* Check for null expression. */
if (is_delim(delim)) {
TRACEP("expr_end", printf("null expr: (%s)\n", pr_op(delim)));
return;
}
for (;;) {
exp_term();
if(is_delim(delim)) {
break;
}
if (is_binop(token) || is(QUESTION_TOK) || is(COLON_TOK)) {
exp_op();
}
else {
err3( "Binary or ternary operator expected at '",
pr_tok(),
"'");
if(needend(delim) == FALSE) {
break;
}
}
}
TRACEP("expr_end", printf("(%s)\n", pr_op(delim)));
}
/*
Parse an expression, assumed to end with delim or comma.
*/
void
expr1(en_tokens delim)
{
TRACEP("expr1", printf("(%s)\n", pr_op(delim)));
/* Check for null expression. */
if (is(COMMA_TOK) || is_delim(delim)) {
error("Null expression");
return;
}
for (;;) {
exp_term();
if(is(COMMA_TOK) || is_delim(delim)) {
break;
}
if (is_binop(token) || is(QUESTION_TOK) || is(COLON_TOK)) {
exp_op();
}
else {
err3( "Binary or ternary operator expected at '",
pr_tok(),
"'");
if(needend(delim) == FALSE) {
break;
}
}
}
TRACEP("expr1_end", printf("(%s)\n", pr_op(delim)));
}
/* ============== Internally visible routines =============== */
/*
Parse one or more array subscripts.
*/
static void
exp_index(void)
{
TRACETOK("exp_index");
while(is(LBRACK_TOK)) {
/* Eat the '[' */
get_token();
expr(RBRACK_TOK);
need(RBRACK_TOK);
}
}
/*
Parse an infix (binary or ternary) operator.
*/
static void
exp_op(void)
{
TRACETOK("exp_op");
get_token();
}
/*
Parse zero or one post operators.
*/
static void
exp_postop(void)
{
TRACETOK("exp_postop");
if (is(INC_TOK) || is(DEC_TOK)) {
/* Convert to post operators. */
get_token();
}
}
/*
Parse a list of prefix operators: unary op, prefix ++ or --, or casts.
Return TRUE if a left paren was over-run.
*/
static bool
exp_preop(void)
{
TRACETOK("exp_preop");
for (;;) {
if(is_unop(token) ||
is(PLUS_TOK) || is(MINUS_TOK) || is(STAR_TOK) ||
is(INC_TOK) || is(DEC_TOK)
) {
get_token();
}
else if (is(LPAREN_TOK)) {
/* Eat the '(' */
get_token();
if (is_type()) {
/* Parse the cast. */
type_name();
}
else {
return TRUE;
}
}
else {
return FALSE;
}
}
}
/*
Parse a term: pre op, id part, post op.
Call expr() recursively to handle array indices, function arguments and
parenthesized expressions.
NOTE: no semantic checks are done to make sure that a construction
makes sense in the context in which it appears.
NOTE: the following are all potentially valid id parts:
f(x) [25]
(*abc) (abc, xyz)
(*abc) [25]
0x25 (abc, xyz)
"abc" [25]
*/
static void
exp_term(void)
{
bool lparen_seen;
TRACETOK("exp_term");
/* Sets over-run if went past a non-cast '(' */
lparen_seen = exp_preop();
if (lparen_seen || is(ID_TOK) || is(INT_TOK) || is(LONG_TOK)) {
if (lparen_seen) {
/* Eat the expression, which might be a pointer. */
expr(RPAREN_TOK);
need(RPAREN_TOK);
}
else {
/* Eat the id or constant. */
get_token();
}
/* function calls and array subscripts are allowed. */
if (is(LPAREN_TOK)) {
/* Parse the list of actual parameters */
get_token();
expr(RPAREN_TOK);
need(RPAREN_TOK);
}
if (is(LBRACK_TOK)) {
exp_index();
}
}
else if (is(CHAR_TOK) || is(FLOAT_TOK)) {
/*
Character or floating CONSTANT.
No subscripting or function calls allowed.
*/
get_token();
}
else if (is(STRING_TOK)) {
/*
String constant.
Subscripting IS allowed.
*/
get_token();
if (is(LBRACK_TOK)) {
exp_index();
}
}
else if (is(K_SIZEOF)) {
get_token();
if (is(LPAREN_TOK)) {
get_token();
type_name();
}
else {
exp_term();
}
}
exp_postop();
}
/*
Return TRUE if token may validly appear in an expression.
Keywords, braces, and semicolons may not.
*/
bool
is_expr_tok(void)
{
TRACETOK("is_expr_tok");
if ( is_key(token) || is(SEMICOLON_TOK) ||
is(RCURLY_TOK) || is(LCURLY_TOK) ||
is(EOP_TOK)
) {
return FALSE;
}
else {
return TRUE;
}
}
/*
Return TRUE if we are at the end of an expression supposedly
delimited by delim.
Semicolons and curly braces ALWAYS abort the expression.
Note that this is the same convention used by needend().
Eat misplaced ')' and ']' tokens with a warning.
Bug fix: 6/22/89: Allow { or } if curly_ok_flag is TRUE;
*/
static bool
is_delim(en_tokens delim)
{
TRACEP("is_delim", printf("(%s)\n", pr_op(delim)));
for (;;) {
if (is(delim)) {
return TRUE;
}
else if (is(RPAREN_TOK) || is(RBRACK_TOK)) {
err3( "Unmatched '",
pr_tok(),
"' in expression ignored");
get_token();
}
else if (is(EOP_TOK)) {
error("Unexpected end of file in expression");
return TRUE;
}
else if ( curly_ok_flag &&
(is(RCURLY_TOK) || is(LCURLY_TOK))
) {
/* { and } are also valid delimiters. */
return TRUE;
}
else if (is(RCURLY_TOK) ||
is(LCURLY_TOK) ||
is(SEMICOLON_TOK)
) {
err3( "Unexpected '",
pr_tok(),
"' in expression");
/* Abort the expression. */
return TRUE;
}
else {
/* Not a delimiter. */
return FALSE;
}
}
}